﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace Inaction.Criteria
{
    [Serializable]
    public abstract class CriteriaBase
    {
        readonly static Dictionary<Type, Dictionary<FieldInfo, CriteriaFieldAttribute>> typeCriteriaFields = new Dictionary<Type, Dictionary<FieldInfo, CriteriaFieldAttribute>>();

        public Dictionary<FieldInfo, CriteriaFieldAttribute> LoadCriteriaFields()
        {
            var type = this.GetType();
            if (typeCriteriaFields.ContainsKey(type)) return typeCriteriaFields[type];
            var criteriaFields = new Dictionary<FieldInfo, CriteriaFieldAttribute>();
            var fields = this.GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
            foreach (var field in fields)
            {
                if (field.FieldType.IsSubclassOf(typeof(CriteriaBase)))
                {
                    criteriaFields.Add(field, null);
                    continue;
                }
                var criteriaField = field.GetCustomAttribute<CriteriaFieldAttribute>();
                if (criteriaField == null) continue;
                criteriaFields.Add(field, criteriaField);
            }
            typeCriteriaFields.Add(type, criteriaFields);
            return criteriaFields;
        }
        public static CriteriaFieldAttribute GetSimilarFieldCriteriaFieldAttribute(Type type, string propertyName)
        {
            Dictionary<FieldInfo, CriteriaFieldAttribute> fields = null;
            if (typeCriteriaFields.ContainsKey(type))
            {
                fields = typeCriteriaFields[type];
            }
            else
            {
                var method = type.GetMethod("LoadCriteriaFields", BindingFlags.Instance | BindingFlags.Public);
                fields = (Dictionary<FieldInfo, CriteriaFieldAttribute>)method.Invoke(type.GetConstructor(new Type[] { }).Invoke(new object[] { }), null);
            }
            foreach( var field in fields)
            {
                if(propertyName.ToLower().StartsWith(field.Key.Name.Replace("_","").ToLower()))
                {
                    return field.Value;
                }
            }
            return null;
        }
        private Int32 recordCount = 0;
        [System.ComponentModel.Browsable(false)]
        public Int32 RecordCount
        {
            get { return recordCount; }
            set { recordCount = value; }
        }
    }
}